#include "code.h"
#include <math.h>
#include <string.h>

const double HIGH_VOLTAGE = -15.0;      // 逻辑1
const double LOW_VOLTAGE = 15.0;        // 逻辑0
const double VOLTAGE_THRESHOLD = 5.0;   // 电压阈值，用于解码时判断逻辑值

// 编码函数：将消息转换为电压序列
int rs232c_encode(double *volts, int volts_size, const char *msg, int size) {
    int volt_index = 0;
    int i, bit;
    unsigned char c;

    for (i = 0; i < size; ++i) {
        c = msg[i] & 0x7F; // 获取字符的7位ASCII码

        // 检查是否有足够空间存储11个电压值（1空闲 + 1起始 + 7数据 + 1停止 + 1空闲）
        if (volt_index + 11 > volts_size) {
            return -1; // 空间不足
        }

        // 空闲位（逻辑1）
        volts[volt_index++] = HIGH_VOLTAGE;

        // 起始位（逻辑0）
        volts[volt_index++] = LOW_VOLTAGE;

        // 7位数据位（从最低位到最高位）
        for (bit = 0; bit < 7; ++bit) {
            if (c & (1 << bit)) {
                volts[volt_index++] = HIGH_VOLTAGE; // 逻辑1
            } else {
                volts[volt_index++] = LOW_VOLTAGE;  // 逻辑0
            }
        }

        // 停止位（逻辑1）
        volts[volt_index++] = HIGH_VOLTAGE;

        // 空闲位（逻辑1）
        volts[volt_index++] = HIGH_VOLTAGE;
    }
    return volt_index; // 返回实际输出的电压值个数
}

// 解码函数：将电压序列转换回消息
int rs232c_decode(char *msg, int size, const double *volts, int volts_size) {
    int msg_index = 0;
    int volt_index = 0;
    unsigned char c;
    int bit;

    while (volt_index + 10 < volts_size) { // 需要至少11个电压值解码一个字符
        // 检查起始位：第二个电压应为逻辑0（+15V）
        if (volts[volt_index + 1] > VOLTAGE_THRESHOLD) {
            c = 0;
            // 提取7位数据位（从最低位到最高位）
            for (bit = 0; bit < 7; ++bit) {
                if (volts[volt_index + 2 + bit] < -VOLTAGE_THRESHOLD) {
                    c |= (1 << bit); // 设置对应的位
                }
            }
            // 检查停止位：第10个电压应为逻辑1（-15V）
            if (volts[volt_index + 9] < -VOLTAGE_THRESHOLD) {
                if (msg_index < size) {
                    msg[msg_index++] = c;
                } else {
                    return -1; // 消息缓冲区不足
                }
            } else {
                return -1; // 停止位错误
            }
            volt_index += 11; // 移动到下一个字符的起始
        } else {
            volt_index++; // 继续搜索起始位
        }
    }
    return msg_index; // 返回解码出的字符数
}